﻿using System;
using System.Threading;

namespace MFGLib
{
	/// <summary>
	///  由Form计时器监控的线程，可在OnStart和OnStop中安全操作由主线程创建的Form控件
	/// </summary>
	public class FormThread : IDisposable
	{
		/// <summary>
		/// 线程运行开始前的回调函数，在此函数中可以安全地操作Form控件
		/// </summary>
		public ThreadStart OnStart { get; set; }

		/// <summary>
		/// 线程操作过程函数，在此函数中不应该操作Form控件（除非控件已继承并实现跨线程Invoke）
		/// </summary>
		public ThreadStart OnProcess { get; set; }

		/// <summary>
		/// 线程运行结束后的回调函数，在此函数中可以安全地操作Form控件
		/// </summary>
		public ThreadStart OnStop { get; set; }

		/// <summary>
		/// 线程是否正在运行中
		/// </summary>
		public bool IsAlive => m_thread != null && m_thread.IsAlive;

		/// <summary>
		/// 监控线程运行间隔，默认为100（毫秒）
		/// </summary>
		public int MonitorInterval { get; set; } = 100;

		/// <summary>
		/// 监控计时器，周期性检查线程是否结束，结束时调用OnStop()
		/// </summary>
		private System.Windows.Forms.Timer m_timer = null;

		/// <summary>
		/// 内部线程
		/// </summary>
		private Thread m_thread = null;

		/// <summary>
		/// 默认构造函数
		/// </summary>
		public FormThread()
		{
			m_timer = new System.Windows.Forms.Timer();
			m_timer.Tick += new EventHandler(OnTimerTick);
		}

		/// <summary>
		/// 析构函数
		/// </summary>
		~FormThread()
		{
			Dispose();
		}

		/// <summary>
		/// 对象销毁
		/// </summary>
		public virtual void Dispose()
		{
			Stop();
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// 启动线程
		/// </summary>
		public virtual void Start()
		{
			Stop();
			m_thread = new Thread(new ThreadStart(_ThreadProc));
			m_thread.IsBackground = true;
			m_thread.Start();
			OnStart?.Invoke();
			m_timer.Interval = Math.Max(10, MonitorInterval);
			m_timer.Enabled = true;
		}

		/// <summary>
		/// 终止线程
		/// </summary>
		public virtual void Stop()
		{
			if (IsAlive)
			{
				m_thread.Abort();
			}			
		}		

		// 内部计时器定时回调
		private void OnTimerTick(object sender, EventArgs e)
		{
			if (IsAlive)
			{
				return;
			}

			m_timer.Enabled = false;
			OnStop?.Invoke();
		}
		
		private void _ThreadProc()
		{
			OnProcess?.Invoke();
		}
	}

	/// <summary>
	/// 用于处理OnProcess逻辑较为复杂的线程，继承类必须重载ThreadProc
	/// </summary>
	public abstract class FormWorkerThread : FormThread
	{
		/// <summary>
		/// 启动线程
		/// </summary>
		public override void Start()
		{
			OnProcess = ThreadProc;
			base.Start();
		}

		protected abstract void ThreadProc();
	}
}
